package ru.home.documentmanager.controller;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import ru.home.documentmanager.model.FileDoc;
import ru.home.documentmanager.model.User;
import ru.home.documentmanager.model.UserData;
import ru.home.documentmanager.service.DocService;
import ru.home.documentmanager.service.DocXService;
import ru.home.documentmanager.service.FileDocService;
import ru.home.documentmanager.service.UserDataService;
import ru.home.documentmanager.service.UserService;

@Controller
public class FileController extends AppController {

    @Value("${replace.patronymic:patronymic}")
    private String PATRONYMIC;

    @Value("${replace.lastName:lastName}")
    private String LAST_NAME;

    @Value("${replace.firstName:firstName}")
    private String FIRST_NAME;

    @Value("${replace.passport:passport}")
    private String PASSPORT;

    @Resource
    private UserService userService;

    @Resource
    private FileDocService fileDocService;

    @Resource
    private UserDataService userDataService;

    @Resource
    private DocService docService;

    @Resource
    private DocXService docXService;

    @RequestMapping("/files")
    public ModelAndView list() {
        ModelAndView mav = new ModelAndView("user/files");
        User user = userService.find(getCurrentUser().getId());
        userService.initFiles(user);
        mav.addObject("files", user.getFiles());
        return mav;
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {
        if (!file.isEmpty()) {
            try {

                byte[] bytes = file.getBytes();
                String name = file.getOriginalFilename();

                FileDoc fileDoc = fileDocService.find(name, getCurrentUser());
                if (fileDoc != null) {
                    return "redirect:/files";
                }

                fileDoc = new FileDoc();
                fileDoc.setName(name);
                fileDoc.setData(bytes);

                User user = userService.find(getCurrentUser().getId());

                fileDoc.setUser(user);

                fileDocService.save(fileDoc);

                return "redirect:/files";
            } catch (Exception e) {
                e.printStackTrace();
                return "redirect:/error";
            }
        } else {
            return "redirect:/error";
        }
    }

    @RequestMapping(value = "/files/{file_id}", method = RequestMethod.GET)
    public void getFile(@PathVariable("file_id") long id,
            HttpServletResponse response) {
        try {
            User user = getCurrentUser();
            FileDoc file = fileDocService.find(id);
            if (file == null) {
                return;
            }
            String ext = StringUtils.getFilenameExtension(file.getName());

            byte[] data = file.getData();

            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment; filename=\""
                    + file.getName() + "\"");

            Map<String, String> placeholders = createPreplacementMap(userDataService
                    .findByUser(user));

            if (ext.equals("doc")) {

                docService.replacePlaceholders(new ByteArrayInputStream(data),
                        new BufferedOutputStream(response.getOutputStream()),
                        placeholders);

            } else if (ext.equals("docx")) {
                System.out.println("docx");
                docXService.replacePlaceholders(new ByteArrayInputStream(data),
                        new BufferedOutputStream(response.getOutputStream()),
                        placeholders);
            }
            response.flushBuffer();
        } catch (Exception ex) {
            throw new RuntimeException("IOError writing file to output stream",
                    ex);
        }

    }

    @RequestMapping(value = "/files/delete/{file_id}", method = RequestMethod.GET)
    public String delete(@PathVariable("file_id") long id) {
        fileDocService.delete(id);
        return "redirect:/files";
    }

    private Map<String, String> createPreplacementMap(UserData userData) {
        Map<String, String> placeholders = new HashMap<>();
        placeholders.put(FIRST_NAME, userData.getFirstName());
        placeholders.put(LAST_NAME, userData.getLastName());
        placeholders.put(PATRONYMIC, userData.getPatronymic());
        placeholders.put(PASSPORT, Long.toString(userData.getPassportNumber()));
        return placeholders;
    }
}
